package com.iwop.moto.utils.weixin.utils;


import com.iwop.moto.comm.Comm;
import com.iwop.moto.model.SuperRecordModel;
import com.iwop.moto.utils.http.HttpUtils;
import com.iwop.moto.utils.http.XMLUtil;
import com.iwop.moto.utils.stringUtil.*;
import com.iwop.moto.utils.weixin.model.RequestHandler;
import com.iwop.moto.utils.weixin.model.WxPayDto;
import org.jdom.JDOMException;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

import static com.iwop.moto.comm.Comm.partnerkey;

public class WxPayUtil {

	public static final String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	/** 微信APP支付 **/
	public static final String openAppId = "wx03b0c5f337e483b5";
	public static final String openAppSecret = "60126de4ff4aca89d4032745b7692101";
	public static final String openPartner = "1407520002";
	public static final String openPartnerKey = "60126de4ff4aca89d4032745b7692101";

	public static final String DYopenAppId    = "wxcfe785a85fd972bd";                //开摩邦订阅号APPID(正式环境)
	public static final String DYopenAppSecret   = "86785b89366c6e520381e9338af5e4fb";
	public static final String DYopenPartner  = "1416813302"; //开摩邦订阅商户号
	public static final String DYopenPartnerKey = "86785b89366c6e520381e9338af5e4fb";//开摩邦订阅商户号Key




	/**
	 * @功能: 微信App支付
	 * @参数: total_fee 金额
	 * @参数: attach 附件数据
	 * @参数: body 商品描述
	 * @参数: spbill_create_ip IP
	 */
	public static SortedMap<String, String> WxAppPay(SuperRecordModel srmParam){
		SortedMap<String, String> sortedMap = new TreeMap<String, String>();
		sortedMap.put("appid",openAppId);
		sortedMap.put("attach",srmParam.getString("attach"));
		sortedMap.put("body",srmParam.getString("body"));
		sortedMap.put("mch_id",openPartner);
		sortedMap.put("nonce_str", DateFormatter.simpleDateTimeUnionFormat(new Date()));
		sortedMap.put("trade_type", "APP");
		sortedMap.put("total_fee", srmParam.getString("total_fee"));
		sortedMap.put("out_trade_no", srmParam.getString("outTradeNo"));
		sortedMap.put("spbill_create_ip", "127.0.0.1");
		sortedMap.put("notify_url", Comm.HTTP_URL + Comm.appnotifyurl);
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(openAppId, openAppSecret, openPartner);
		String sign = reqHandler.createSign(sortedMap,openPartnerKey);
		sortedMap.put("sign",sign);
		String xml = XMLUtil.getRequestStrXml(sortedMap);
		String prepayId = new GetWxOrderno().getPayNo(createOrderURL, xml);
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		finalpackage.put("appid", openAppId);
		finalpackage.put("partnerid", openPartner);
		finalpackage.put("prepayid", prepayId);
		finalpackage.put("package", "Sign=WXPay");
		finalpackage.put("noncestr", sortedMap.get("nonce_str"));
		finalpackage.put("timestamp", timestamp);
		String finalsign = reqHandler.createSign(finalpackage,openPartnerKey);//要签名
		finalpackage.put("sign",finalsign);
		return finalpackage;
	}

	/**
	 * @功能: 微信App支付
	 * @参数: total_fee 金额
	 * @参数: attach 附件数据
	 * @参数: body 商品描述
	 * @参数: spbill_create_ip IP
	 */
	public static SortedMap<String, String> DYWxAppPay(SuperRecordModel srmParam){
		SortedMap<String, String> sortedMap = new TreeMap<String, String>();
		sortedMap.put("appid",DYopenAppId);
		sortedMap.put("attach",srmParam.getString("attach"));
		sortedMap.put("body",srmParam.getString("body"));
		sortedMap.put("mch_id",DYopenPartner);
		sortedMap.put("nonce_str", DateFormatter.simpleDateTimeUnionFormat(new Date()));
		sortedMap.put("trade_type", "APP");
		sortedMap.put("total_fee", srmParam.getString("total_fee"));
		sortedMap.put("out_trade_no", srmParam.getString("outTradeNo"));
		sortedMap.put("spbill_create_ip", "127.0.0.1");
		sortedMap.put("notify_url", Comm.HTTP_URL + Comm.appnotifyurl);
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(DYopenAppId, DYopenAppSecret, DYopenPartner);
		String sign = reqHandler.createSign(sortedMap,DYopenPartnerKey);
		sortedMap.put("sign",sign);
		String xml = XMLUtil.getRequestStrXml(sortedMap);
		String prepayId = new GetWxOrderno().getPayNo(createOrderURL, xml);
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		finalpackage.put("appid", DYopenAppId);
		finalpackage.put("partnerid", DYopenPartner);
		finalpackage.put("prepayid", prepayId);
		finalpackage.put("package", "Sign=WXPay");
		finalpackage.put("noncestr", sortedMap.get("nonce_str"));
		finalpackage.put("timestamp", timestamp);
		String finalsign = reqHandler.createSign(finalpackage,DYopenPartnerKey);//要签名
		finalpackage.put("sign",finalsign);
		return finalpackage;
	}


	/**
	 * 验证回调签名
	 * @param result
	 * @return
	 */
//	public static boolean checksign(Map result){
//		SortedMap<String, String> packageParams = mapToSort(result);
//		RequestHandler reqHandler = new RequestHandler(null, null);
//		reqHandler.init(appid, appsecret, partnerkey);
//		String sign = reqHandler.createSign(packageParams);
//		return sign.equals(result.get("sign"));
//	}

	/**
	 * 将map对象转成排序对象
	 * @param map
	 * @return
	 */
	public static SortedMap<String, String> mapToSort(Map map){
		SortedMap<String, String> sort =  new TreeMap<String, String>();
		Set es = map.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			sort.put((String)entry.getKey(), (String) entry.getValue());
		}
		return sort;
	}

	/**
	 * @功能:微信扫码支付 (二维码)
	 * @return 返回微信支付二维码url地址
	 */
	@SuppressWarnings("static-access")
	public static String getCodeurl(WxPayDto tpWxPayDto) {

		// 订单号
		String orderId = tpWxPayDto.getOrderId();
		// 附加数据 原样返回
		String attach = "attach:附加数据 原样返回";
		// 总金额以分为单位，不带小数点
		String totalFee = WxPayUtil.getMoney(tpWxPayDto.getTotalFee());
		// 订单生成的机器 IP
		String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
		// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
		String notify_url = tpWxPayDto.getNotifyUrl();
		String trade_type = "NATIVE";
		// 商户号
		String mch_id = Comm.partner;
		// 随机字符串
		String nonce_str = WxPayUtil.getNonceStr();
		// 商品描述根据情况修改
		String body = tpWxPayDto.getBody();
		// 商户订单号
		String out_trade_no = orderId;
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", Comm.APPID);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		packageParams.put("attach", attach);
		packageParams.put("out_trade_no", out_trade_no);
		// 这里写的金额为1 分到时修改
		packageParams.put("total_fee", totalFee);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);
		packageParams.put("trade_type", trade_type);
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(Comm.APPID, Comm.SECRET, partnerkey);
		String sign = reqHandler.createSign(packageParams);
		String xml = "<xml>" + "<appid>" + Comm.APPID + "</appid>" + "<mch_id>" + mch_id + "</mch_id>" + "<nonce_str>"
				+ nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>" + "<body><![CDATA[" + body + "]]></body>"
				+ "<out_trade_no>" + out_trade_no + "</out_trade_no>" + "<attach>" + attach + "</attach>"
				+ "<total_fee>" + totalFee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
				+ "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>" + trade_type
				+ "</trade_type>" + "</xml>";
		String code_url = "";
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml);
		return code_url;
	}

	/**
	 * @功能: 微信支付 (H5)
	 */
	public static SuperRecordModel wxH5Pay(SuperRecordModel srmParam){
		SuperRecordModel srm = new SuperRecordModel();
		String  openid = srmParam.getString("openid");
		String  out_trade_no = srmParam.getString("out_trade_no");
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", Comm.APPID);
		packageParams.put("mch_id", Comm.partner);
		packageParams.put("nonce_str", ObjectId.UUID());
		packageParams.put("body", srmParam.getString("body"));
		packageParams.put("attach", srmParam.getString("attach"));
		packageParams.put("out_trade_no", out_trade_no);
		packageParams.put("total_fee", srmParam.getString("total_fee")); // 这里写的金额为1 分到时修改
		packageParams.put("spbill_create_ip", "127.0.0.1");
		packageParams.put("notify_url", srmParam.getString("notify_url"));
		packageParams.put("trade_type", "JSAPI");
		packageParams.put("openid", openid);
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(Comm.APPID, Comm.SECRET, partnerkey);
		String sign = reqHandler.createSign(packageParams);
		String xml = "<xml>" + "<appid>" + Comm.APPID + "</appid>" + "<mch_id>" + packageParams.get("mch_id") + "</mch_id>"
				+ "<nonce_str>" + packageParams.get("nonce_str") + "</nonce_str>" + "<sign>" + sign + "</sign>"
				+ "<body><![CDATA[" + packageParams.get("body") + "]]></body>" + "<out_trade_no>" + out_trade_no + "</out_trade_no>"
				+ "<attach>" + packageParams.get("attach") + "</attach>" + "<total_fee>" + packageParams.get("total_fee") + "</total_fee>"
				+ "<spbill_create_ip>" + packageParams.get("spbill_create_ip") + "</spbill_create_ip>" + "<notify_url>" + packageParams.get("notify_url")
				+ "</notify_url>" + "<trade_type>" + packageParams.get("trade_type") + "</trade_type>" + "<openid>" + packageParams.get("openid")
				+ "</openid>" + "</xml>";
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		String prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
		//获取prepay_id后，拼接最后请求支付所需要的package
		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		String packages = "prepay_id=" + prepay_id;
		finalpackage.put("appId", Comm.APPID);
		finalpackage.put("timeStamp", timestamp);
		finalpackage.put("nonceStr", packageParams.get("notify_url"));
		finalpackage.put("package", packages);
		finalpackage.put("signType", "MD5");
		String finalsign = reqHandler.createSign(finalpackage);//要签名
		srm.put("appId", Comm.APPID);
		srm.put("timeStamp", timestamp);
		srm.put("nonceStr", packageParams.get("notify_url"));
		srm.put("packageStr", packages);
		srm.put("paySign", finalsign);
		return srm;
	}

	/**
	 * 用户端微信付款查询订单
	 *
	 * orderId 用户订单
	 *
	 * type user
	 * */
	public static Map<Object,String> getUserWxOrderInfo(String orderId,String payId,String type){
		Map<Object,String> wxParam = getWXParam(type);
		String queryUrl="https://api.mch.weixin.qq.com/pay/orderquery";
		SortedMap<String, String> sortedMap = new TreeMap<String, String>();
		sortedMap.put("appid",wxParam.get("openId"));
		sortedMap.put("mch_id",wxParam.get("oPartner"));
		if(StringUtils.isEmpty(payId)){
			sortedMap.put("out_trade_no",orderId);
		}else {
			sortedMap.put("transaction_id",payId);
		}
		sortedMap.put("nonce_str", SequenceUtil.Serial());
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(wxParam.get("openId"), wxParam.get("oAppSecret"), wxParam.get("oPartner"));
		String sign = reqHandler.createSign(sortedMap,wxParam.get("oPartnerKey"));
		sortedMap.put("sign",sign);
		String xml = XMLUtil.getRequestStrXml(sortedMap);
		String result = new GetWxOrderno().getPayObject(queryUrl, xml);
		try {
			Map map = XMLUtil.doXMLParse(result);
			return map;
		} catch (JDOMException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	private static Map<Object,String> getWXParam(String type){
		Map<Object,String> param=new HashMap<Object,String>();
		if(type.equals("user")){
			param.put("openId",DYopenAppId);
			param.put("oPartner",DYopenPartner);
			param.put("oAppSecret",DYopenAppSecret);
			param.put("oPartnerKey",DYopenPartnerKey);

		}else if(type.equals("store")){
			param.put("openId",openAppId);
			param.put("oPartner",openPartner);
			param.put("oAppSecret",openAppSecret);
			param.put("oPartnerKey",openPartnerKey);
		}else {
			param.put("oPartner",Comm.partner);
			param.put("openId",Comm.APPID);
			param.put("oAppSecret",Comm.SECRET);
			param.put("oPartnerKey", partnerkey);
		}
		return param;
	}

	public static String refuceMoney(Map<Object,String> map,String type){
		Map<Object, String> wxParam = getWXParam(type);
		String queryUrl="https://api.mch.weixin.qq.com/secapi/pay/refund";
		SortedMap<String, String> sortedMap = new TreeMap<String, String>();
		sortedMap.put("appid",map.get("appid"));
		sortedMap.put("mch_id",map.get("oPartner"));
		sortedMap.put("out_trade_no",map.get("out_trade_no"));
		sortedMap.put("out_refund_no",SequenceUtil.Serial("Back"));
		sortedMap.put("nonce_str", SequenceUtil.Serial());
		sortedMap.put("total_fee", map.get("total_fee"));
		sortedMap.put("refund_fee", map.get("total_fee"));
		sortedMap.put("op_user_id",map.get("oPartner"));
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(wxParam.get("openId"), wxParam.get("oAppSecret"), wxParam.get("oPartner"));
		String sign = reqHandler.createSign(sortedMap,wxParam.get("oPartnerKey"));
		sortedMap.put("sign",sign);
		String xml = XMLUtil.getRequestStrXml(sortedMap);
		String result = new GetWxOrderno().getPayObject(queryUrl, xml);
		try {
			Map xmlParse = XMLUtil.doXMLParse(result);
			return (String)xmlParse.get("result_code");
		} catch (JDOMException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) {
		getUserWxOrderInfo("","4006622001201702271548741812", "user");
	}

	/**
	 * 获取随机字符串
	 * @return
	 */
	public static String getNonceStr() {
		// 随机数
		String currTime = TenpayUtil.getCurrTime();
		// 8位日期
		String strTime = currTime.substring(8, currTime.length());
		// 四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		// 10位序列号,可以自行调整。
		return strTime + strRandom;
	}

	/**
	 * 元转换成分
	 * @param amount
	 * @return
	 */
	public static String getMoney(String amount) {
		if (amount == null) {
			return "";
		}
		// 金额转化为分为单位
		String currency = amount.replaceAll("\\$|\\￥|\\,", ""); //处理包含, ￥ 或者$的金额
		int index = currency.indexOf(".");
		int length = currency.length();
		Long amLong = 0l;
		if (index == -1) {
			amLong = Long.valueOf(currency + "00");
		} else if (length - index >= 3) {
			amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
		} else if (length - index == 2) {
			amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
		} else {
			amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
		}
		return amLong.toString();
	}

	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

}
	
	










